#pragma once

#include <iostream>
#include "Sock.hpp"
#include <memory>
#include <sys/select.h>
#include <cstring>

class Selectserver
{
    static const int fd_num_max_ = sizeof(fd_set) * 8;

public:
    Selectserver()
        : sock_ptr_(new Sock)
    {
        for (int i = 0; i < fd_num_max_; i++)
            fd_array[i] = -1;
    }

    void Init(uint16_t port)
    {
        sock_ptr_->Socket();
        sock_ptr_->Bind(port);
        sock_ptr_->Listen();
        fd_array[0] = sock_ptr_->Get_fd();
    }

    void Accept(int listen_fd)
    {
        struct sockaddr_in client;
        socklen_t len = sizeof(client);
        int sockfd = accept(listen_fd, (sockaddr *)&client, &len);
        if (sockfd < 0)
        {
            Log(Warning) << "accept failed";
        }

        // 将该字段加入到数组中
        // 先找位置
        int pos = 0;
        for (; pos < fd_num_max_ && fd_array[pos] != -1; pos++)
            ;

        if (pos == fd_num_max_)
        {
            Log(Warning) << "fd_array filled";
            close(sockfd);
        }
        else
        {
            fd_array[pos] = sockfd;
        }
        Log(Info) << "get a connect , sockfd :" << sockfd;
    }

    void Handlerway(int fd_ , int pos)
    {
        char buffer[1024];
        memset(buffer , sizeof(buffer) , 0);

        int n = read(fd_ , buffer , sizeof(buffer) - 1);
        if(n > 0)
        {
            buffer[n] = 0;
            std::string ret = "echo#" ;
            ret += buffer;
            write(fd_ , ret.c_str() , ret.size());
        }
        else if(n == 0)
        {
            fd_array[pos] = -1;
            close(fd_);
        }
        else 
        {
            Log(Warning) << "read failed";
        }
    }

    void Dispenser(fd_set *rfst)
    {
        int listen_fd = sock_ptr_->Get_fd();
        for (int i = 0; i < fd_num_max_; i++)
        {
            if (fd_array[i] == -1 || !FD_ISSET(fd_array[i] , rfst))
                continue;
            if (fd_array[i] == listen_fd)
            {
                // 可以进行accept
                Accept(fd_array[i]);
            }
            else
            {
                Handlerway(fd_array[i] , i);
            }
        }
    }

    void Run()
    {
        int listen_fd = sock_ptr_->Get_fd();
        while (1)
        {
            // struct timeval timeout{1, 0};
            // 直接进行accept
            fd_set rfst;
            FD_ZERO(&rfst);
            int max_num = 0;

            for (int i = 0; i < fd_num_max_; i++)
            {
                if(fd_array[i] == -1) continue;
                FD_SET(fd_array[i], &rfst);
                max_num = std::max(max_num , fd_array[i]);
            }

            int n = select(max_num + 1, &rfst, nullptr, nullptr, nullptr);
            if (n > 0)
            {
                // 有资源就绪，需要进行处理
                Dispenser(&rfst);
            }
            else if (n == 0)
            {
                // 没有资源就绪
                Log(Info) << "I an waiting for you";
            }
            else
            {
                // 出错
                Log(Warning) << "select fail";
            }
        }
    }

private:
    std::shared_ptr<Sock> sock_ptr_;
    uint16_t port_;
    int fd_array[fd_num_max_];
};
